章節一、方程式操作 & 微分與極值


Posted by pei_______ on 2022-06-22

前導:程式與數值計算關係

1.統計分析 vs. 機器學習
統計:找出真相、因果推理
機器:解決問題、預測結果

2.數學:解決問題的方法

<線性>
(1)如何解決問題-方程式
(2)固定&變動資訊-截距&斜率
(3)瞬間變化量-微分
(4)趨近值-極限

<非線性>
(5)敘述統計:聚集、離散程度
(6)推論統計:資料無法探索
(7)機率、分配
(8)母體、抽樣、檢定、標準差


Google Colab

  1. 環境:Ubuntu + Python3.7
  2. 套件:每次執行都得重新安裝
  3. 檔案:執行完就會刪除
  4. 免費版本不能於背景執行

一、線性方程式:求斜率&截距

matplotlib.pyplot - Documentation

numpy - Documentation


01. Set (in Google Colab)

# !pip install matplotlib
# !pip install numpy
# ! 表示轉移至Linux環境下達指令 (離開python環境)

import matplotlib.pyplot as plt
import numpy as np

x = [1,2,3,4,5,6,7]
y = [1,3,3,12,5,7,9]
plt.plot(x,y,'--') # x軸、y軸、虛線表示
plt.grid() # 增加格線
plt.show() # 顯示圖形


02. 轉換成線性方程式(斜率、截距)

# 令有一次方程式: y = slope * x + intercept
# np.polyfit(x,y,N): 可將現資料(x,y)調整找出N次方程式, 回傳list

slope, intercept = np.polyfit(x,y,1) 
print(slope)
print(intercept)

# 若拆解成二次方程式 (y = a * x ** 2 + b * x + c)
# 等號左邊可以得幾個值,視等號右邊會拆成幾個變數
a, b, c =  np.polyfit(x,y,2)
print(data)

# 以一次方程式為例,列出每一個x值所對應y值(list)
y1 = [slope * i + intercept for i in x]
plt.plot(x,y,'--')
plt.plot(x,y1,'r') #red
plt.grid()
plt.show()


練習一、經濟部1994-2004年經濟成長率

x = np.arange(1994,2005,1) # 1994-2005,1年1格
y = [7.11,6.42,6.10,6.37,4.33,5.32,5.78,-2.22,3.94,3.33,5.71]

# 以 polyfit 求一次方程式,以進行預測
slope, intercept = np.polyfit(x,y,1)

print(f"斜率: {slope}")
print(f"截距: {intercept}")

# 產生list: 每一個x所對應的y值
y1 = [slope * i + intercept for i in x]

plt.plot(x,y,'--')
plt.plot(x,y1,'r') #red
plt.grid()
plt.show()


# 試求二次方程式 (y = a * x ** 2 + b * x + c)

a, b, c = np.polyfit(x,y,2)
y1 = [a * i ** 2 + b * i + c for i in x]

plt.plot(x,y,'--')
plt.plot(x,y1,'r') #red
plt.grid()
plt.show()



練習二、銷售業績計算(CSV)

  • 若數值凌亂不一定可以推出線性方程式 => 以最近鄰概念進行推估
  • 建議最高至三元(三欄位)即可,可以3D圖表呈現
  • 連結google drive內檔案
from google.colab import drive
drive.mount('/content/drive', force_remount=True)

# force_remount=True 強制安裝驅動器,避免中斷情形
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

df = pd.read_csv("/content/drive/MyDrive/colab/Advertising.csv")
x = df['Newspaper']
y = df['Sales']

plt.scatter(x,y) # 使用散佈圖
# plt.plot(x,y) # 使用曲線圖

plt.show()


# 加入polyfit找出資料中的線性關係
a,b,c = np.polyfit(x,y,2)
y1 = [a * i ** 2 + b * i + c for i in x]

plt.scatter(x, y)
plt.plot(x, y1, "r")
plt.show()


資料過於零散,無法得出有效表示關係之方程式


二、解方程式

  1. 需先以物件 = sympy.Symbol('符號')定義函式內物件
  2. f(x) = 0聯立方程式 => 求變數解
    • sympy.solve([input],[output]) 求解(回傳dictionary)
  3. 線性方程式 f(x) = ax+by+c => 求每一變數對應值
    • sympy.lambdify((x, y), function)sympy.Lambda((x, y), funciton)建立物件計算
  4. 二次函數極值與圖形
    • numpy.arange限定範圍求var.argmin()var.argmax()
    • matplotlib.pyplot.scatter(x,y)散佈圖點出極值位置
    • 亦可微分(.diff)求解(.solve)並帶回原式(.lambdify)

二元一次聯立方程式

# eg 1.
import sympy as sp
import numpy as np

x = sp.Symbol('x')
y = sp.Symbol('y')
f1 = 2 * x + 3 * y - 23
f2 = x + 4 * y - 24

print(sp.solve([f1, f2], [x, y]))

> {x: 4, y: 5}
# eg 2.
# 有草莓(50元)、巧克力(30元)兩種冰淇淋
s = sp.Symbol('s')
c = sp.Symbol('c')

# 總數量 = 20個
f1 = s + c - 20
# 總金額 = 800元
f2 = 50 * s + 30 * c - 800

# f1, f2 表示兩個答案為零的方程式
answer = sp.solve([f1, f2], [s, c])
print(answer)
print(answer.__class__) # 回傳資料的屬性
print(type(answer)) # 回傳資料的型態

print("草莓冰淇淋份數: ", answer[s])
print("巧克力冰淇淋份數: ", answer[c])

> {s: 10, c: 10}
> <class 'dict'>
> <class 'dict'>
> 草莓冰淇淋份數:  10
> 巧克力冰淇淋份數:  10

線性方程式求解 lambdify vs. Lambda


from sympy import lambdify, Symbol, Lambda
import numpy as np

'''
lambdify vs. Lambda

ddx = lambdify(自變數, 方程式)
answer = ddx(自變數代入數值)

func = Lambda(自變數, 方程式)
answer = func(自變數代入數值)
'''

print("\n\n----- 若x = -1,求一階導數的結果 -----")

x = sp.Symbol('x')
y1 = 2 * np.power(x,4) - 3 * np.power(x,2) + 2 * x - 20
print("\n原方程式: ", y1)

y2 = y1.diff(x)
print("一階函式: ", y2)

y3 = 8 * (-1) ** 3 - 6 * (-1) + 2
print("\n【法1】直接代入: ",y3)

ddx = lambdify(x, y2)
print("\n【法2】使用lambdify: ",ddx(-1))

func = sp.Lambda(x, y2)
print("\n【法3】使用Lambda: ",func(-1))


print("\n\n----- 使 x = -5 ~ 5,判斷函式圖形 -----")

ddx = lambdify(x, y1)
print("\n【法1】使用lambdify:", ddx(np.arange(-5, 5, 1)))

func = Lambda(x, y1)
# print(func(np.arange(-5, 5, 1))) => error
print("\n【法2】使用Lambda: errer - 無法代入list")

print("\n\n----- 若x = 3, y = 7,二元方程式求解 -----")

x = sp.Symbol('x')
y = sp.Symbol('y')

f = x ** 2 - 2 * y + 4 * x -3

print("\n令二元方程式: ", f)

ddx = lambdify((x, y), f)
print("\n【法1】使用lambdify: ", ddx(3, 7))
func = Lambda((x, y), f)
print("\n【法2】使用Lambda: ", func(3, 7))


print("\n**lambdify物件: ", ddx.__class__)
print("**Lambda物件: ", func.__class__)


二次函數-極值與圖形

import sympy as sp


print("\n---- 令x為正負10以內整數,求極值 ----")

x = np.arange(-10, 11, 1)
y = -3 * x ** 2 + 20 * x + 3
y_max = np.max(y)
x_max = x[y.argmax()]
print("\n求圖形最高點: ", x_max, ",", y_max)

print("\n---- 繪製二次函數圖形 (放大、並標示最大值) ----")

# 放大圖表
plt.figure(figsize=(8, 5))
plt.plot(x, y)

# 以散佈圖方式點出最大值
plt.scatter(x_max, y_max, c='r') 
plt.grid()
plt.show()

print("\n---- 以微分求極值 ----")

x = sp.Symbol("x")
y = -3 * x ** 2 + 20 * x + 3

y_diff = y.diff(x)
x_max = sp.solve([y_diff],[x])[x]
ddf = sp.lambdify(x, y)
y_max = ddf(x_max)
print("\n求圖形最高點: ", x_max, ",", y_max)


三、微分與極值

  1. 一次函數 f'(x) = f.diff(x)
  2. 極限函式 sympy.limit(函式, 自變數,趨近值)
  3. sp.oo 表示無限大
# ---------- 微分 ---------- #

# 意義:求瞬間變化量

x = sp.Symbol('x')
y = np.power(x,5)+ 2*np.power(x,4)+ 3*np.power(x,3)+ 4*np.power(x,2)+ 5*x+ 6

y2 = y.diff(x) # 對y做x的微分
print(y2)

> 5*x**4 + 8*x**3 + 9*x**2 + 8*x + 5


# ---------- 極限 ---------- #

# 意義:求 x = ? 會使 函式 趨近於 趨近值

x = sp.Symbol('x')
f3 = sp.limit((x**2+2*x-3)/(x-1),x,sp.oo)
print(f3)

> oo









Related Posts

[Day 04] - Vault dynamic secrets engine - AWS

[Day 04] - Vault dynamic secrets engine - AWS

Laravel 7 passing collection to anonymous components

Laravel 7 passing collection to anonymous components

What Type of Laser Engraving Machine Should be Used for Stainless Steel Engraving?

What Type of Laser Engraving Machine Should be Used for Stainless Steel Engraving?


Comments